package com.around.test.m3u8.util;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Base64;

/**
 * ZeroPadding填充
 * @program: community
 * @description:
 * @author: moodincode
 * @create: 2020/9/2
 **/
public class AesUtils {
    private static final Logger log= LoggerFactory.getLogger(AesUtils.class);
    /**
     * 默认的加密算法
     */
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/NoPadding";
    private static final String CHAR_SET = "UTF-8";

    /**
     * AES 加密操作
     *
     * @param content  待加密内容
     * @param password 加密密码
     * @return
     */
    public static String encrypt(String content, String password) {
        try {
            // 创建密码器
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            int blockSize = cipher.getBlockSize();
            byte[] byteContent = content.getBytes();
            int plaintextLength = byteContent.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(byteContent, 0, plaintext, 0, byteContent.length);
            // 初始化为加密模式的密码器
            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));
            //return cipher.doFinal(plaintext);// 加密
            return Base64.getEncoder().encodeToString(cipher.doFinal(plaintext));
        } catch (Exception ex) {
           log.error("[AES工具类]内容加密失败:content={},原因:{}{}",content,ex, ex.getMessage());
        }
        return null;
    }

    /**
     * AES 解密操作
     *
     * @param content
     * @param password
     * @return
     */
    public static String decrypt(String content, String password) {
        try {
            // 实例化
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            // 初始化为加密模式的密码器
            cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));
            // 执行操作
            // 解密
            byte[] result = cipher.doFinal(Base64.getDecoder().decode(content));
            return new String(result, CHAR_SET);
        } catch (Exception ex) {
            log.error("[AES工具类]内容解密失败:content={},原因:{}{}",content,ex, ex.getMessage());
        }
        return null;
    }

    /**
     * 生成加密秘钥
     *
     * @return
     */
    private static SecretKeySpec getSecretKey(final String password) {
        int len = password.getBytes().length;
        if (len % 16 != 0) {
            len = len + (16 - (len % 16));
        }
        byte[] newpass = new byte[len];
        System.arraycopy(password.getBytes(), 0, newpass, 0, password.getBytes().length);
        SecretKeySpec keySpec = new SecretKeySpec(newpass, "AES");
        return keySpec;
    }

    /**
     * CBC AES/CBC/PKCS5PADDING解密
     * @param content
     * @param password
     * @return
     */
    public static String decryptCBC(String content, String password,byte[] iv) {
        try {
            if(iv==null){
                iv = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            }
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            SecretKeySpec secretKeySpec = new SecretKeySpec(password.getBytes("UTF-8"), "AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivspec);
            return new String(cipher.doFinal(Base64.getDecoder().decode(content)));
        } catch (Exception ex) {
            log.error("[AES工具类]内容解密失败:content={},原因:{}{}",content,ex, ex.getMessage());
        }
        return null;
    }
    /**
     * CBC AES/CBC/PKCS5PADDING加密
     * @param content
     * @param password
     * @return
     */
    public static String encryptCBC(String content, String password,byte[] iv) {
        try {

            if(iv==null){
                iv = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            }
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            SecretKeySpec secretKeySpec = new SecretKeySpec(password.getBytes("UTF-8"), "AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivspec);
            byte[] plaintext = Base64.getDecoder().decode(content);
            return Base64.getEncoder().encodeToString(cipher.doFinal(plaintext));
        } catch (Exception ex) {
            log.error("[AES工具类]内容加密失败:content={},原因:{}{}",content,ex, ex.getMessage());
        }
        return null;
    }
    /**
     * CBC AES/CBC/PKCS5PADDING加密
     * @param content
     * @param password
     * @return
     */
    public static InputStream decryptCBC(InputStream content, String password, byte[] iv) {
        try {

            if(iv==null){
                iv = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            }
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            SecretKeySpec secretKeySpec = new SecretKeySpec(password.getBytes("UTF-8"), "AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivspec);
            byte[] plaintext=IOUtils.toByteArray(content);
            byte[] doFinal = cipher.doFinal(plaintext);
            return new ByteArrayInputStream(doFinal);
        } catch (Exception ex) {
            log.error("[AES工具类]内容加密失败:content={},原因:{}{}","二进制",ex, ex.getMessage());
        }
        return null;
    }
    /**
     * CBC AES/CBC/PKCS5PADDING加密
     * @param content
     * @param password
     * @return
     */
    public static InputStream decryptCBC(InputStream content, byte[] password, byte[] iv) {
        try {

            if(iv==null){
                iv = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            }
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            SecretKeySpec secretKeySpec = new SecretKeySpec(password, "AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivspec);
            byte[] plaintext=IOUtils.toByteArray(content);
            byte[] doFinal = cipher.doFinal(plaintext);
            return new ByteArrayInputStream(doFinal);
        } catch (Exception ex) {
            log.error("[AES工具类]内容加密失败:content={},原因:{}{}","二进制",ex, ex.getMessage());
        }
        return null;
    }
    /**
     * CBC AES/CBC/PKCS5PADDING加密
     * @param content json字符串
     * @param password
     * @return
     */
    public static String encryptCBC2(String content, String password) {
        try {
            byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            SecretKeySpec secretKeySpec = new SecretKeySpec(password.getBytes("UTF-8"), "AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivspec);
            byte[] plaintext =content.getBytes("UTF-8");
            return Base64.getEncoder().encodeToString(cipher.doFinal(plaintext));
        } catch (Exception ex) {
            log.error("[AES工具类]内容加密失败:content={},原因:{}{}",content,ex, ex.getMessage());
        }
        return null;
    }
    public static void main(String[] args) throws UnsupportedEncodingException {

    }

}